package cn.iocoder.yudao.module.crm.controller.admin.task;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.crm.controller.admin.task.vo.*;
import cn.iocoder.yudao.module.crm.controller.admin.task.vo.taskapprover.TaskApproverReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.task.vo.taskcontent.TaskContentDetail;
import cn.iocoder.yudao.module.crm.controller.admin.task.vo.taskoperationlog.TaskOperationLogDetail;
import cn.iocoder.yudao.module.crm.controller.admin.task.vo.taskoperationlog.TaskOperationLogRespVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.task.TaskContentDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.task.TaskDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.task.TaskOperationLogDO;
import cn.iocoder.yudao.module.crm.enums.task.CrmTaskOperationStatus;
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
import cn.iocoder.yudao.module.crm.service.task.TaskApproverService;
import cn.iocoder.yudao.module.crm.service.task.TaskContentService;
import cn.iocoder.yudao.module.crm.service.task.TaskOperationLogService;
import cn.iocoder.yudao.module.crm.service.task.TaskService;
import cn.iocoder.yudao.module.crm.service.tasktype.TaskTypeService;
import cn.iocoder.yudao.module.crm.service.user.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;

@Tag(name = "管理后台 - CRM 任务单")
@RestController
@RequestMapping("/crm/task")
@Validated
public class TaskController {

    @Resource
    private TaskService taskService;
    @Resource
    private TaskTypeService taskTypeService;
    @Resource
    private TaskApproverService taskApproverService;
    @Resource
    private TaskOperationLogService taskOperationLogService;
    @Resource
    private TaskContentService taskContentService;
    @Resource
    private CrmCustomerService customerService;
    @Resource
    private CrmContractService contractService;
    @Resource
    private CrmProductService productService;
    @Resource
    private UserService userService;

    @PostMapping("/create")
    @Operation(summary = "创建CRM 任务单")
    @PreAuthorize("@ss.hasPermission('crm:task:create')")
    public CommonResult<Long> createTask(@Valid @RequestBody TaskSaveReqVO createReqVO) {
        return success(taskService.createTask(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新CRM 任务单")
    @PreAuthorize("@ss.hasPermission('crm:task:update')")
    public CommonResult<Long> updateTask(@Valid @RequestBody TaskSaveReqVO updateReqVO) {
        return success(taskService.updateTask(updateReqVO));
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除CRM 任务单")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('crm:task:delete')")
    public CommonResult<Boolean> deleteTask(@RequestParam("id") Long id) {
        taskService.deleteTask(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得CRM 任务单基本信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:task:query')")
    public CommonResult<TaskRespVO> getTaskBase(@RequestParam("id") Long id) {
        TaskDO task = taskService.getTask(id);
        return success(BeanUtils.toBean(task, TaskRespVO.class));
    }

    @GetMapping("/detail")
    @Operation(summary = "获得CRM 任务单详情信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:task:query')")
    public CommonResult<TaskDetailRespVO> getTaskDetail(@RequestParam("id") Long id) {
        TaskDO task = taskService.getTask(id);
        // 关联的任务单内容
        List<TaskContentDO> taskContentList = taskContentService.getTaskContentListByTaskId(id);
        TaskDetailRespVO taskDetailRespVO = new TaskDetailRespVO();
        taskDetailRespVO.setId(task.getId())
            .setCode(task.getCode())
            .setIssueTime(task.getIssueTime())
            .setTaskTypeName(taskTypeService.getTaskType(task.getTaskTypeId()).getName())
            .setCustomerName(customerService.getCustomer(task.getCustomerId()).getName())
            .setContractName(contractService.getContract(task.getContractId()).getName())
            .setProductName(productService.getProduct(task.getProductId()).getName())
            .setUsername(userService.getUserNamesById(task.getUserId()))
            .setDealTime(task.getUpdateTime())
            .setContent(convertList(taskContentList, taskContentDO -> new TaskContentDetail()
                    .setId(taskContentDO.getId()).setName(taskContentDO.getName())
                    .setDetail(taskContentDO.getDetails())
                    .setInputMethod(taskContentDO.getInputMethod())));
        return success(taskDetailRespVO);
    }

    @GetMapping("/page")
    @Operation(summary = "获得CRM 任务单分页")
    @PreAuthorize("@ss.hasPermission('crm:task:query')")
    public CommonResult<PageResult<TaskPageRespVO>> getTaskPage(@Valid TaskPageReqVO pageReqVO) {
        PageResult<TaskDO> pageResult = taskService.getTaskPage(pageReqVO);
        PageResult<TaskPageRespVO> voPageResult = new PageResult<>();
        List<TaskDO> list = pageResult.getList();
        // 预先收集所有需要查询的ID集合
        Set<Long> taskIds = list.stream().map(TaskDO::getId).collect(Collectors.toSet());
        Set<Long> taskTypeIds = list.stream().map(TaskDO::getTaskTypeId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> customerIds = list.stream().map(TaskDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> contractIds = list.stream().map(TaskDO::getContractId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> productIds = list.stream().map(TaskDO::getProductId).filter(Objects::nonNull).collect(Collectors.toSet());
        Set<Long> userIds = list.stream().map(TaskDO::getUserId).filter(Objects::nonNull).collect(Collectors.toSet());
        // 批量查询相关实体
        Map<Long, String> taskTypeNameMap = taskTypeService.getTaskTypeNamesByIds(taskTypeIds);
        Map<Long, String> customerNameMap = customerService.getCustomerNamesByIds(customerIds);
        Map<Long, String> contractNameMap = contractService.getContractNamesByIds(contractIds);
        Map<Long, String> productNameMap = productService.getProductNamesByIds(productIds);
        Map<Long, String> userNameMap = userService.getUserNamesByIds(userIds);
        Map<Long, TaskIsApproverRespVO> isApproverMap = taskApproverService.getIsApproverByTaskIds(taskIds);

        voPageResult.setList(convertList(list, task -> new TaskPageRespVO()
                .setId(task.getId()).setCode(task.getCode())
                .setIssueTime(task.getIssueTime())
                .setTaskTypeName(taskTypeNameMap.getOrDefault(task.getTaskTypeId(),""))
                .setCustomerName(customerNameMap.getOrDefault(task.getCustomerId(),""))
                .setContractName(contractNameMap.getOrDefault(task.getContractId(),""))
                .setProductName(productNameMap.getOrDefault(task.getProductId(),""))
                .setUsername(userNameMap.getOrDefault(task.getUserId(),""))
                .setDealTime(task.getUpdateTime())
                .setIsApprover(isApproverMap.get(task.getId()).getIsApprover())
                .setReviewStatus(isApproverMap.get(task.getId()).getReviewStatus())
        ));
        voPageResult.setTotal(pageResult.getTotal());
        return success(voPageResult);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出CRM 任务单 Excel")
    @PreAuthorize("@ss.hasPermission('crm:task:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportTaskExcel(@Valid TaskPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<TaskDO> list = taskService.getTaskPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "CRM 任务单.xls", "数据", TaskRespVO.class,
                        BeanUtils.toBean(list, TaskRespVO.class));
    }

    @GetMapping("/getOperation")
    @Operation(summary = "获得CRM 任务单操作记录")
    @Parameter(name = "id", description = "任务单编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:task:query')")
    public CommonResult<TaskOperationLogRespVO> getOperation(@RequestParam("id") Long id) {
        List<TaskOperationLogDO> list = taskOperationLogService.getOperationByTaskId(id);
        TaskOperationLogRespVO taskOperationLogRespVO = new TaskOperationLogRespVO();
        taskOperationLogRespVO.setId(id)
                .setOperation(convertList(list, taskOperationLogDO -> new TaskOperationLogDetail()
                .setUsername(taskOperationLogService.getUsernameById(taskOperationLogDO.getUserId()))
                .setOperationTime(taskOperationLogDO.getUpdateTime())
                .setOperationStatus(CrmTaskOperationStatus.getNameByStatus(taskOperationLogDO.getOperationStatus()))));
        // 预先收集所有需要查询的ID集合
        return success(taskOperationLogRespVO);
    }

    @PutMapping("/deal")
    @Operation(summary = "处理CRM 任务单")
    @PreAuthorize("@ss.hasPermission('crm:task:update')")
    public CommonResult<Long> dealTask(@Valid @RequestBody TaskDetailReqVO taskDetailReqVO) {
        return success(taskContentService.updateTaskContent(taskDetailReqVO));
    }

    @PutMapping("/approver")
    @Operation(summary = "审核CRM 任务单")
    @PreAuthorize("@ss.hasPermission('crm:task:update')")
    public CommonResult<Long> approverTask(@Valid @RequestBody TaskApproverReqVO taskApproverReqVO) {
        return success(taskApproverService.updateApprover(taskApproverReqVO));
    }
}